package com.ygsoft.nio.fileserver;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class ClientWorker extends Thread {
	
	//private int port ;
	private SocketChannelQueue channelQueue = null;
	private Selector readSelector = null;
	private ByteBuffer readBuffer;
	
	public ClientWorker(SocketChannelQueue channelQueue) throws IOException {
		this.channelQueue = channelQueue;
		this.readSelector = Selector.open();
		
		this.readBuffer = ByteBuffer.allocate(4096);
	}
	
	public Selector getReadSelector(){
		return this.readSelector;
	}
	
	public void run(){
		System.out.println("Active Worker..");
		while(true){
			try {
				this.processSocketChannelQueue();
				
				int numKeys = this.readSelector.select();
				if(numKeys > 0){
					// Read and Send Data
					this.processRequest();
				}
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void processRequest() throws IOException {
		Iterator<SelectionKey> iter = this.readSelector.selectedKeys().iterator();
		
		while(iter.hasNext()){
			SelectionKey key = iter.next();
			iter.remove();
			
			if(!key.isValid() || !key.channel().isOpen() 
					|| ((SocketChannel)key.channel()).socket().isClosed()){
				System.out.println(">Invalid key..");
				key.cancel();
				continue;
			}
			
			try{
				//this.readData(key);
				this.receiveBigData(key);
				
			}catch(IOException e){
				System.out.println("Invalid Key..");
				key.cancel();
				key.channel().close();
			}
		}
	}
	
	private void receiveBigData(SelectionKey key) throws IOException {
		System.out.println("Recv Data..");
		
		SocketChannel sChannel = (SocketChannel)key.channel();
		this.readBuffer.clear();
				
		int rCount = sChannel.read(this.readBuffer);
		if(rCount == -1){
			System.out.println("Socket is closed..");
			key.cancel();
			return ;
		}
		
		this.readBuffer.flip();
		DataController dataController = (DataController)key.attachment();
		dataController.processData(readBuffer);
	}
	
	private void readData(SelectionKey key) throws IOException {
		SocketChannel sChannel = (SocketChannel)key.channel();
//		if(!(sChannel.isConnected() && sChannel.isOpen())) {
//			key.cancel();
//			return;
//		} 
		int rCount = sChannel.read(this.readBuffer);
		if(rCount == -1){
			System.out.println("Socket is closed..");
			key.cancel();
			return ;
		}
		this.readBuffer.flip();
		StringBuffer requestString = (StringBuffer)key.attachment();
		requestString.append(new String(this.readBuffer.array()));
		
		this.readBuffer.clear();
		
		System.out.println("Request >" + requestString);
	}
	
	private void processSocketChannelQueue() throws IOException {
		SocketChannel socketChannel = null;
		while ( (socketChannel = channelQueue.getFirst()) != null) {
			socketChannel.configureBlocking(false);
			//socketChannel.register(readSelector, SelectionKey.OP_READ, new StringBuffer());
			socketChannel.register(readSelector, SelectionKey.OP_READ, new DataController());
		}
//		try {
//			System.out.println("Stopped..");
//			Thread.sleep(100);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}
	
	public static void main(String ... v) {
		;
	}
	
}
